##############################################################################
##
## Select-GraphicalFilteredObject.ps1
##
## Adapted from Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
## Display a Windows Form to help the user select a list of items piped in.
## Any selected items get passed along the pipeline.
##
## ie:
##
##      PS >dir | Select-GraphicalFilteredObject -Title "Select items to delete" | Delete-Item -Whatif
##
##############################################################################

[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

function Get-CheckboxSelectForm 
	( [array]$ObjectList,
    [string]$title = "Select the list of objects you wish to pass down the pipeline",
		[switch]$checkOnClick=$TRUE
	)
{
	function SelectAllCheckedListBoxItems(
			#[Windows.Forms.CheckedListBox]$checkedListBox,
			$checkedListBox,
			[bool]$selected = $TRUE
	)
	{
			for ($i = 0; $i -lt $checkedListBox.Items.Count; $i++) { 
					$checkedListBox.SetItemChecked( $i, $selected ) 
			} 
	}
	#region Form Setup
	## Load the Windows Forms assembly
	
	$controlSpacing = 7

	## Create the main form
	$form = New-Object Windows.Forms.Form
	$form.Size = New-Object Drawing.Size @(600,600)
	$form.Padding = New-Object Windows.Forms.Padding(4)
	
	## Create the listbox to hold the items from the pipeline
	$listbox = New-Object Windows.Forms.CheckedListBox
	$listbox.Name = "CheckList"
	$listbox.CheckOnClick = $checkOnClick
	$listbox.Dock = "Fill"
	$listbox.Sorted = $TRUE
	
	$form.Text = $title
	$listBox.Items.AddRange($ObjectList)
	
	## Create the button panel to hold the OK and Cancel buttons
	$buttonPanel = New-Object Windows.Forms.Panel
	$buttonPanel.Size = New-Object Drawing.Size @(600,30)
	$buttonPanel.Dock = "Bottom"
	
	## Create the Cancel button, which will anchor to the bottom right
	$cancelButton = New-Object Windows.Forms.Button
	$cancelButton.Text = "Cancel"
	$cancelButton.DialogResult = "Cancel"
	$cancelButton.Top = $buttonPanel.Height - $cancelButton.Height - $controlSpacing
	$cancelButton.Left = $buttonPanel.Width - $cancelButton.Width - $controlSpacing - $controlSpacing
	$cancelButton.Anchor = "Right"
	
	## Create the OK button, which will anchor to the left of Cancel
	$okButton = New-Object Windows.Forms.Button
	$okButton.Text = "Ok"
	$okButton.DialogResult = "Ok"
	$okButton.Top = $cancelButton.Top
	$okButton.Left = $cancelButton.Left - $okButton.Width - $controlSpacing
	$okButton.Anchor = "Right"
	
	## Create the None button, which will anchor to the left of OK
	$noneButton = New-Object Windows.Forms.Button
	$noneButton.Text = "&None"
	$noneButton.Top = $cancelButton.Top
	$noneButton.Left = $okButton.Left - $noneButton.Width - $controlSpacing
	$noneButton.Anchor = "Right"
	$noneButton.add_Click( { SelectAllCheckedListBoxItems $listbox $FALSE } )
	
	## Create the All button, which will anchor to the left of None
	$allButton = New-Object Windows.Forms.Button
	$allButton.Text = "&All"
	$allButton.Top = $cancelButton.Top
	$allButton.Left = $noneButton.Left - $allButton.Width - $controlSpacing
	$allButton.Anchor = "Right"
	$allButton.add_Click( { SelectAllCheckedListBoxItems $listbox $TRUE } )
	
	## Add the buttons to the button panel
	$buttonPanel.Controls.Add($noneButton)
	$buttonPanel.Controls.Add($allButton)
	$buttonPanel.Controls.Add($okButton)
	$buttonPanel.Controls.Add($cancelButton)
	
	## Add the button panel and list box to the form, and also set
	## the actions for the buttons
	$form.Controls.Add($listBox)
	$form.Controls.Add($buttonPanel)
	$form.AcceptButton = $okButton
	$form.CancelButton = $cancelButton
	$form.Add_Shown( { $form.Activate() } )
	#endregion
	
	$form
	$listBox
}

function Select-GraphicalFilteredObject (
    [string]$title = "Select the list of objects you wish to pass down the pipeline",
    [switch]$checkOnClick=$TRUE
)
{

$CheckBoxForm,$CheckList = . Get-CheckboxSelectForm -ObjectList @($Input) -Title $title -checkOnClick:$checkOnClick

## Ensure that they've piped information into the script
if($objectArray.Count -eq 0)
{
    Write-Error "This script requires pipeline input."
    return
}

# $CheckList.SetItemChecked(2,$TRUE)

## Show the form, and wait for the response
$result = $CheckBoxForm.ShowDialog()

## If they pressed OK (or Enter,) go through all the
## checked items and send the corresponding object down the pipeline
if($result -eq "OK")
{
    foreach($index in $CheckList.CheckedIndices)
    {
        $objectArray[$index]
    }
}
}
